/**********************************************************
 * Copyright © 2024 Walkline Wang (https://walkline.wang)
 * Gitee: https://gitee.com/walkline/keypad-for-ops
 **********************************************************/
#include "src/common.h"
#include "src/drivers/ws2812.h"
#include "src/effect.h"
#include "src/keypad.h"

WS2812 Leds;
KEYPAD KeyPad;
EFFECT Effect;

void setup() {
    Serial.begin(UART1_BAUDRATE);
    while (!Serial) {
        ;
    }

    KeyPad.setup();

    waiting_for_chip_ready(true);

    Leds.setup();
    Leds.brightness(0.2f);

    uint8_t key_status;

    KeyPad.get_keys_status();

    for (uint8_t index = 0; index < IO_COUNT; index++) {
        if (KeyPad.key_changed(index, key_status)) {
            KeyPad.switch_effect();
            break;
        }
    }
}

void loop() {
    uint8_t key_status, key_index, keycode;
    bool kb_key_changed = false;

    show_light_effect();

    KeyPad.get_keys_status();

    for (uint8_t index = 0; index < IO_COUNT; index++) {
        if (KeyPad.key_changed(index, key_status)) {
            key_index = KeyPad.get_layer_index(index);
            keycode = KeyPad.get_keycode(key_index);

            switch (KeyPad.process_hid_data(key_status, keycode)) {
            case KeyPad.KEYBOARD:
                kb_key_changed = true;
                break;
            }

#if DEBUG_PROMPT
            Serial.print("key ");
            Serial.print(key_index);
            Serial.println(key_status == KeyPad.PRESSED ? " down" : " up");
#endif
        }
    }

    KeyPad.send_kb_hid_data(kb_key_changed);
}

/* 显示灯光效果 */
void show_light_effect() {
    uint8_t color[3];

    switch (KeyPad.light_effect) {
    case 0:
        uint8_t index;

        Effect.rainbow(index, color);
        Leds.set_color(index, WS2812::ws2812_color_t(color));

        break;
    case 1:
        unsigned long now = millis();
        static unsigned long last_time_light = 0;

        if (now - last_time_light > KeyPad.light_speed) {
            last_time_light = now;

            Effect.gradient(color);
            Leds.set_color(LEDS_ALL, WS2812::ws2812_color_t(color));
        }

        break;
    }
}

/*
 * @brief: 等待 CH9329 芯片连接到 PC 并识别
 * @param: wait 等待状态
 *     -true 等待连接识别并打印状态信息
 *     -false 仅打印状态信息
 */
void waiting_for_chip_ready(bool wait) {
    if (wait) {
        /* 两次 while 循环用于解决 USB 插入时的抖动 */
        while (KeyPad.get_chip_info() != CH9329_GET_INFO ||
               !KeyPad.chip_info.usb_status) {
            delay(200);
        }

        while (KeyPad.get_chip_info() != CH9329_GET_INFO ||
               !KeyPad.chip_info.usb_status) {
            delay(200);
        }
    }

    Serial.println("\nChip Info Updated");
#if DEBUG_PROMPT
    Serial.print("- chip version: ");
    Serial.println(KeyPad.chip_info.version);
    Serial.print("- num_lock: ");
    Serial.println(KeyPad.chip_info.num_lock ? "on" : "off");
    Serial.print("- caps_lock: ");
    Serial.println(KeyPad.chip_info.caps_lock ? "on" : "off");
    Serial.print("- scroll_lock: ");
    Serial.println(KeyPad.chip_info.scroll_lock ? "on" : "off");
#endif
}
